package com.zhima.frame;

import com.zhima.function.ConfigurationIndexAssociate;
import com.zhima.function.RemoveSelectedRow;
import com.zhima.panel.*;
import com.zhima.task.GenerateInDataTask;
import com.zhima.util.StrUtil;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainFrame extends JFrame {
    public static final Integer AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
    public static final String DEFAULT_BASE_DIR = System.getenv("USERPROFILE") + File.separator + "temp";
    private JPanel randomInDataConfigurationsContainer;
    private List<RandomInDataConfiguration> randomInDataConfigurations;
    private RemoveSelectedRow removeSelectedRandomInDataConfiguration;
    private ConfigurationIndexAssociate configurationIndexAssociate;
    private JTextField numberOfConfigurationJTextFiled;
    private JLabel selectedInFileOutputJLabel;
    private JButton addRandomInDataConfigurationJButton;
    private JButton addNewLineConfigurationJButton;
    private JButton selectInFileOutputBaseDirJButton;
    private JButton generateInDataJButton;
    private JFileChooser inFileOutputBaseDirJFileChooser;
    protected JButton confirmAllConfigurationsJButton;
    protected JButton removeAllConfigurationsJButton;
    protected JButton editAllConfigurationsJButton;
    protected JButton previewInDataFormatJButton;
    private final Set<Integer> randomInDataConfigurationIndexCanBeAssociated = new TreeSet<>();
    private final ExecutorService executorService = Executors.newFixedThreadPool(AVAILABLE_PROCESSORS);


    public MainFrame() {
        super("测试用例生成器");
        setIconImage(RandomInDataConfiguration.getImageIcon("imgs/logo.png", 300, 300).getImage());
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setBounds(300, 10, 1100, 950);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        initComponents();
        ShowCodePanel showCodePanel = new ShowCodePanel();
        InFileHeadPanel inFileHeadPanel = new InFileHeadPanel(addRandomInDataConfigurationJButton, addNewLineConfigurationJButton, selectInFileOutputBaseDirJButton, selectedInFileOutputJLabel, numberOfConfigurationJTextFiled, generateInDataJButton);
        inFileHeadPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
        add(inFileHeadPanel, BorderLayout.WEST);
        JPanel p = new JPanel(new BorderLayout());
        p.add(showCodePanel, BorderLayout.EAST);
        p.add(new SelectCodePanel(numberOfConfigurationJTextFiled, showCodePanel.getCodeJTextArea(), selectedInFileOutputJLabel), BorderLayout.WEST);
        add(p, BorderLayout.EAST);
        JPanel randomInDataConfigurationOuterContainer = new JPanel(new BorderLayout());
        randomInDataConfigurationOuterContainer.setPreferredSize(new Dimension(1000, 500));
        randomInDataConfigurationOuterContainer.setBorder(BorderFactory.createLineBorder(Color.RED));
        JPanel allOpJPanel = new JPanel();
        allOpJPanel.add(confirmAllConfigurationsJButton);
        allOpJPanel.add(removeAllConfigurationsJButton);
        allOpJPanel.add(editAllConfigurationsJButton);
        allOpJPanel.add(previewInDataFormatJButton);

        randomInDataConfigurationOuterContainer.add(allOpJPanel, BorderLayout.SOUTH);
        JScrollPane randomInDataConfigurationJScrollPane = new JScrollPane(randomInDataConfigurationsContainer);
        randomInDataConfigurationJScrollPane.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
        randomInDataConfigurationOuterContainer.add(randomInDataConfigurationJScrollPane, BorderLayout.CENTER);
        add(randomInDataConfigurationOuterContainer, BorderLayout.SOUTH);

        initActionListener();
    }

    private void initComponents() {
        this.randomInDataConfigurations = new ArrayList<>();
        this.randomInDataConfigurationsContainer = new JPanel(new GridLayout(0, 1));
        this.removeSelectedRandomInDataConfiguration = new RemoveSelectedRow(randomInDataConfigurations, randomInDataConfigurationsContainer);
        this.configurationIndexAssociate = new ConfigurationIndexAssociate(randomInDataConfigurationIndexCanBeAssociated);
        this.addRandomInDataConfigurationJButton = new JButton("添加一块随机数据配置");
        this.addNewLineConfigurationJButton = new JButton("添加换行\\n");
        this.inFileOutputBaseDirJFileChooser = new JFileChooser();
        this.inFileOutputBaseDirJFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        this.selectedInFileOutputJLabel = new JLabel(DEFAULT_BASE_DIR);
        this.selectInFileOutputBaseDirJButton = new JButton("请选择in文件输出目录");
        this.numberOfConfigurationJTextFiled = new JTextField("10", 5);
        this.generateInDataJButton = new JButton("生成输入数据");
        this.removeAllConfigurationsJButton = new JButton("删除所有数据块配置");
        this.confirmAllConfigurationsJButton = new JButton("确认所有数据块配置");
        this.editAllConfigurationsJButton = new JButton("编辑所有数据块配置");
        this.previewInDataFormatJButton = new JButton("预览");
    }

    private void initActionListener() {
        this.addRandomInDataConfigurationJButton.addActionListener(e -> {
            RandomInDataConfiguration newRandomInDataConfiguration = new RandomInDataConfiguration(randomInDataConfigurations.size(), removeSelectedRandomInDataConfiguration, configurationIndexAssociate);
            randomInDataConfigurations.add(newRandomInDataConfiguration);
            randomInDataConfigurationsContainer.add(newRandomInDataConfiguration);
            configurationIndexAssociate.accept(newRandomInDataConfiguration);
            revalidate();
        });
        this.addNewLineConfigurationJButton.addActionListener(e -> {
            NewLineConfiguration newLineConfiguration = new NewLineConfiguration(randomInDataConfigurations.size(), removeSelectedRandomInDataConfiguration, configurationIndexAssociate);
            randomInDataConfigurations.add(newLineConfiguration);
            randomInDataConfigurationsContainer.add(newLineConfiguration);
            revalidate();
        });
        this.selectInFileOutputBaseDirJButton.addActionListener(e -> {
            int result = inFileOutputBaseDirJFileChooser.showOpenDialog(this);
            if (JFileChooser.APPROVE_OPTION == result) {
                File selectedBaseDir = inFileOutputBaseDirJFileChooser.getSelectedFile();
                selectedInFileOutputJLabel.setText(StrUtil.addNewLineIfToLong(selectedBaseDir.getAbsolutePath()));
            }
        });
        this.generateInDataJButton.addActionListener(e -> {
            if (!checkAllCheck()) {
                return;
            }
            executorService.submit(() -> JOptionPane.showMessageDialog(this, "开始生成数据，请稍后！"));
            executorService.submit(new GenerateInDataTask(executorService, randomInDataConfigurations, selectedInFileOutputJLabel, Integer.parseInt(numberOfConfigurationJTextFiled.getText())));
        });
        this.confirmAllConfigurationsJButton.addActionListener(e -> randomInDataConfigurations.forEach(p -> {
            // 防止空指针异常
            if (!(p instanceof NewLineConfiguration)) {
                p.confirmConfiguration();
            } else {
                p.dataAssociationComponentsExitEdited();
            }
        }));
        this.editAllConfigurationsJButton.addActionListener(e -> randomInDataConfigurations.forEach(p -> {
            // 防止空指针异常
            if (!(p instanceof NewLineConfiguration)) {
                p.toEdited();
            } else {
                p.dataAssociationComponentsToEdited();
            }
        }));
        this.removeAllConfigurationsJButton.addActionListener(e -> {
            randomInDataConfigurationsContainer.removeAll();
            randomInDataConfigurations.clear();
            // 这行有两个作用
            // 1、添加一个新的随机数据配置项
            // 2、刷新页面，如果没有这个的话
            // 当配置项没有撑满滚动面板，页面不会重新加载，就会导致旧的数据配置项留在页面上
            // 使用revalidate()没用啊
            addRandomInDataConfigurationJButton.doClick();
        });
        this.previewInDataFormatJButton.addActionListener(e -> {
            if (!checkAllCheck()) {
                return;
            }
            executorService.submit(() -> JOptionPane.showMessageDialog(this, "开始生成预览数据，请稍等"));
            executorService.submit(() -> new PreviewInDataFrame(randomInDataConfigurations).setVisible(true));
        });
    }

    private boolean checkAllCheck() {
        if (randomInDataConfigurations.size() == 0) {
            JOptionPane.showMessageDialog(null, "不是，哥们？一块数据块都不配置啊");
            return false;
        }
        for (RandomInDataConfiguration row : randomInDataConfigurations) {
            if (!(row instanceof NewLineConfiguration) && row.isEdited()) {
                JOptionPane.showMessageDialog(null, "请先确认所有的随机数据块的配置后再生成数据!");
                return false;
            }
        }
        return true;
    }

}
